package xcmg.device.service.agent;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.agent.ServiceBorrowOutDO;
import xcmg.device.dao.entity.agent.ServiceBorrowOutDetailDO;
import xcmg.device.dao.entity.repair.RepairDO;
import xcmg.device.dao.mapper.agent.ServiceBorrowOutMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.exception.CommonBusiExceptions;
import xcmg.device.service.barcode.BarcodeService;
import xcmg.device.service.repair.RepairService;
import xcmg.device.service.vo.agent.ServiceBorrowOutDetailVO;
import xcmg.device.service.vo.barcode.BarcodeManageVO;
import xcmg.device.service.vo.barcode.SplitNumVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryRecordAddVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryRecordBatchAddVO;
import xcmg.device.service.warehouse.WarehouseDeliveryRecordService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * ServiceBorrowOut 后台接口实现类
 *
 * @author huhuawei
 */
@Service
public class ServiceBorrowOutCompose {
    private static final Logger log = LoggerFactory.getLogger(ServiceBorrowOutCompose.class);

    @Autowired
    private BarcodeService barcodeService;

    @Autowired
    private ServiceBorrowOutService serviceBorrowOutService;

    @Autowired
    private ServiceBorrowOutMapper serviceBorrowOutMapper;

    @Autowired
    private ServiceBorrowOutDetailService serviceBorrowOutDetailService;
    
    @Autowired
    private RepairService repairService;

    @Autowired
    private WarehouseDeliveryRecordService warehouseDeliveryRecordService;


    @Transactional
    public void outStock(String id, String userId, String orgId) {
        ServiceBorrowOutDO serviceBorrowOutDO = serviceBorrowOutMapper.item(id);
        if (StringUtils.isEmpty(serviceBorrowOutDO.getRepairNo())) {
            throw new CommonBusiExceptions("没有报修单号");
        }
        if (!serviceBorrowOutDO.getStatus().equals(0)) {
            throw new CommonBusiExceptions("仅未出库状态允许该方式出库");
        }
        List<ServiceBorrowOutDetailDO> detailDOs = queryDetailsByHeadId(id);
        if (CollectionUtils.isEmpty(detailDOs)) {
            throw new CommonBusiExceptions("零件行信息为空");
        }
        for (ServiceBorrowOutDetailDO detailDO : detailDOs) {
            if (null != detailDO && !detailDO.getStatus().equals(0)) {
                throw new CommonBusiExceptions("仅未出库状态允许该方式出库");
            }
        }
        //查询对应报修单上条码信息
        List<RepairDO> repairDOs = repairService.itemByCode(serviceBorrowOutDO.getRepairNo());
        if (CollectionUtils.isEmpty(repairDOs)) {
            throw new CommonBusiExceptions("零件行信息绑定的条码无库存，请用其他方式出库");
        }
        //零件号--条码信息集合
        Map<String, List<RepairDO>> m2Qrs = new HashMap<>();
        //零件号--数量
        Map<String, BigDecimal> m2Amount = new HashMap<>();
        //检查是否是同一个仓库下的，并返回仓库
        String warehouseCode = checkWarehouseCode(repairDOs, m2Qrs, m2Amount);
        log.info("{}", warehouseCode);
        //按尽可能出库策略出库
        tryBestOut(detailDOs, m2Qrs, userId, orgId);
    }

    /**
     * 尽可能出库，库存不足的零件部分出库，库存充足的零件拆分出库
     *
     * @param detailDOs
     * @param m2Qrs
     */
    private void tryBestOut(List<ServiceBorrowOutDetailDO> detailDOs, Map<String, List<RepairDO>> m2Qrs, String userId, String orgId) {
        for (ServiceBorrowOutDetailDO detailDO : detailDOs) {
            if (detailDO.getStatus().equals(2)) {
                //已出库
                continue;
            }
            String materialsNo = detailDO.getMaterialsNo();
            //该零件需要出库的数量
            BigDecimal quantity = detailDO.getQuantity();
            BigDecimal outQ=serviceBorrowOutService.getValueDefaultZero(detailDO.getOutQuantity());
            quantity=quantity.subtract(outQ);
            List<RepairDO> qrs = m2Qrs.get(materialsNo);
            if (CollectionUtils.isEmpty(qrs)) {
                continue;
            }
            for (RepairDO qr : qrs) {
                //若该条码大于出库的数量，进行拆分，否则出库
                if (qr.getAmount().compareTo(quantity) > 0) {
                    //数量满足,该零件全部出库
                    doTryBestOut(detailDO.getBorrowOutNo(), qr.getBarCode(), quantity, userId, orgId, true);
                    break;
                } else {
                    //数量不满足，将该条码全部出库
                    doTryBestOut(detailDO.getBorrowOutNo(), qr.getBarCode(), qr.getAmount(), userId, orgId, false);
                    quantity = quantity.subtract(qr.getAmount());
                }
            }
        }
    }

    private void doTryBestOut(String borrowOutNo, String barCode, BigDecimal quantity, String userId,
                              String orgId, boolean split) {
        try {
            WarehouseDeliveryRecordBatchAddVO batchAddVO = new WarehouseDeliveryRecordBatchAddVO();
            List<WarehouseDeliveryRecordAddVO> recordList = new ArrayList<>();
            WarehouseDeliveryRecordAddVO m = new WarehouseDeliveryRecordAddVO();
            m.setBarCode(barCode);
            if (split) {
                m.setSplitAmount(quantity);
                m.setAmount(quantity);
            } else {
                m.setSplitAmount(BigDecimal.ZERO);
                m.setAmount(quantity);
            }
            m.setBusinessOrder(borrowOutNo);
            recordList.add(m);
            batchAddVO.setRecordList(recordList);
            log.info("doTryBestOut   {}", batchAddVO);
            ErrorCode r = warehouseDeliveryRecordService.batchAdd(batchAddVO, userId, orgId);
            if (r.getCode() != 0) {
                throw new CommonBusiExceptions(r.getDesc());
            }
        } catch (Exception e) {
            log.error("", e);
            throw new CommonBusiExceptions("执行出库发生异常：" + e.getMessage());
        }
    }


    public void bathOut(WarehouseDeliveryRecordBatchAddVO batchAddVO, String userId, String orgId, boolean split) throws Exception {
        //判断数量并自动拆分条码
        WarehouseDeliveryRecordAddVO t = batchAddVO.getRecordList().get(0);
        if (split) {
            SplitNumVO splitNumVO = new SplitNumVO(t.getBarCode(), t.getSplitAmount(), t.getBusinessOrder());
            BarcodeManageVO barcodeManageVO = barcodeService.splitNum(splitNumVO, userId, orgId);
            t.setBarCode(barcodeManageVO.getBarcode());
            t.setAmount(barcodeManageVO.getCurrentQty());
        }
        warehouseDeliveryRecordService.add(t, userId, orgId, true, false);
    }

    /**
     * 校验仓库号，若无冲突收集数据
     *
     * @param repairDOs
     * @param m2Qrs
     * @param m2Amount
     * @return
     */
    private String checkWarehouseCode(List<RepairDO> repairDOs, Map<String, List<RepairDO>> m2Qrs, Map<String, BigDecimal> m2Amount) {
        String r = repairDOs.get(0).getWarehouseCode();
        for (RepairDO dd : repairDOs) {
            List<RepairDO> l = m2Qrs.get(dd.getMaterialsNo());
            BigDecimal b = m2Amount.get(dd.getMaterialsNo());
            if (null == l) {
                l = new ArrayList<>();
            }
            if (null == b) {
                b = BigDecimal.ZERO;
            }
            b=b.add(dd.getAmount());
            l.add(dd);
            m2Qrs.put(dd.getMaterialsNo(), l);
            m2Amount.put(dd.getMaterialsNo(), b);
            if (!r.equals(dd.getWarehouseCode())) {
                throw new CommonBusiExceptions("报修单关联零件条码非同一个仓库下的，请用其他方式出库");
            }
        }
        return r;
    }

    private List<ServiceBorrowOutDetailDO> queryDetailsByHeadId(String id) {
        ServiceBorrowOutDetailVO condition = new ServiceBorrowOutDetailVO();
        condition.setBorrowOutId(id);
        return serviceBorrowOutDetailService.queryList(condition);
    }
}
